//
//  TimeslotManager.m
//  TestTimeStamp
//
//  Created by Chiu Chi Ho on 14/2/13.
//  Copyright (c) 2013 Chiu Chi Ho. All rights reserved.
//

#import "TimeslotManager.h"
#import "TBXML.h"


@interface TimeslotManager ()
{
	NSMutableDictionary *_groupContentDic;
}
@property (nonatomic, retain) NSMutableDictionary *groupContentDic;
@property (nonatomic, retain) NSString *currentGroup;

@end

@implementation TimeslotManager
@synthesize groupContentDic = _groupContentDic;

#pragma mark - Static Function

static TimeslotManager *sharedInstance;
+ (TimeslotManager *)sharedManager
{
	@synchronized(self)
	{
		if(sharedInstance == nil)
			sharedInstance = [[TimeslotManager alloc] init];
	}
	
	return sharedInstance;
}

+ (NSString *)convertToGroupByDigit:(NSInteger)value
{
	if(value == 0 || value == 5)
		return @"A";
	else if(value == 1 || value == 6)
		return @"B";
	else if(value == 2 || value == 7)
		return @"C";
	else if(value == 3 || value == 8)
		return @"D";
	
	return @"E";
}

- (id)init
{
	if(self = [super init])
	{
		self.groupContentDic = [NSMutableDictionary dictionary];
		
		[self reloadTimeslot];
	}
	return self;
}



#pragma mark - Public Function
- (void)reloadTimeslot
{
	[_groupContentDic removeAllObjects];	//Clear all
	
	//NOTE: Uncomment this when wanna request latest
	NSString *timeXmlContent = [self requestTimeXml];	//Request xml
	[self parseContent:timeXmlContent];	//Parse it
	
	//DEBUG: Add xml content here
//	NSString *timeXmlContent  = @"<?xml version='1.0' encoding='utf-8'?><root><item><group>A</group><hour>&lt;p class='ruby'&gt;13&lt;/p&gt;&lt;p class='safa'&gt;20&lt;/p&gt;</hour><day>2/28</day><type>plu</type></item><item><group>D</group><hour>&lt;p class='ruby'&gt;11&lt;/p&gt;&lt;p class='safa'&gt;18&lt;/p&gt;</hour><day>2/28</day><type>plu</type></item><item><group>B</group><hour>&lt;p class='safa'&gt;16&lt;/p&gt;&lt;p class='eme'&gt;21&lt;/p&gt;</hour><day>2/28</day><type>plu</type></item><item><group>C</group><hour>&lt;p class='eme'&gt;10&lt;/p&gt;&lt;p class='ruby'&gt;17&lt;/p&gt;</hour><day>2/28</day><type>plu</type></item><item><group>E</group><hour>&lt;p class='safa'&gt;12&lt;/p&gt;&lt;p class='eme'&gt;19&lt;/p&gt;</hour><day>2/28</day><type>plu</type></item><item><group/><hour/><day/><type/></item><item><group>A</group><hour>12&lt;br&gt;19</hour><day>3/1</day><type>meta</type></item><item><group>B</group><hour>13&lt;br&gt;20</hour><day>3/1</day><type>meta</type></item><item><group>C</group><hour>16&lt;br&gt;21</hour><day>3/1</day><type>meta</type></item><item><group>D</group><hour>10&lt;br&gt;17</hour><day>3/1</day><type>meta</type></item><item><group>E</group><hour>11&lt;br&gt;18</hour><day>3/1</day><type>meta</type></item></root>";
	
	
}

- (NSMutableArray *)getTimeslotByGroup:(NSString *)group
{
	return [_groupContentDic objectForKey:group];
}

- (NSInteger)getNumberOfDay:(NSString *)group
{
	NSMutableDictionary *dateDict = [_groupContentDic objectForKey:group];
	
	return [dateDict count];
}

- (NSString *)getDateStringOnDay:(NSInteger)day	group:(NSString *)group //Zero based
{
	NSMutableDictionary *dateDict = [_groupContentDic objectForKey:group];
	
	int i = 0;
	for(NSString *dateKey in [dateDict allKeys])
	{
		if(i == day)
			return dateKey;
		
		i++;
	}
	
	return @"";
}

- (NSInteger)getNumberOfEventOnDay:(NSInteger)day group:(NSString *)group
{
	NSMutableDictionary *dateDict = [_groupContentDic objectForKey:group];
	
	int i = 0;
	for(NSString *dateKey in [dateDict allKeys])
	{
		if(i == day)
		{
			NSMutableArray *eventArr = [dateDict objectForKey:dateKey];
			return [eventArr count];
		}
		i++;
	}
	
	return 0;
}

- (TimeslotModel *)getTimeslotModelOnDay:(NSInteger)day eventIndex:(NSInteger)index group:(NSString *)group
{
	NSMutableDictionary *dateDict = [_groupContentDic objectForKey:group];

	int i = 0;

	for(NSString *dateKey in [dateDict allKeys])
	{
		if(i == day)
		{
			NSMutableArray *eventArr = [dateDict objectForKey:dateKey];

			TimeslotModel *item = [eventArr objectAtIndex:index];
			return item;
		}
		i++;
	}
	
	return nil;
}

- (void)registerLocalNotificationForGroup:(NSString *)group
{
	NSMutableArray *arr = [self getTimeslotByGroup:group];
	
	for(TimeslotModel *item in arr)
	{
//		UILocalNotification *notif = [[UILocalNotification alloc] init];
//		
//		NSDateComponents *component = [[NSDateComponents alloc] init];
//		NSDate *fireDate = [[NSDate alloc] init];

	}
}

#pragma mark - Private Function
- (NSMutableArray *)parseContent:(NSString *)timeXmlContent
{
	NSLog(@"XML Content : %@", timeXmlContent);
	
	@try
	{
		//Get root
		NSError *err = nil;
		TBXML *xml = [TBXML newTBXMLWithXMLString:timeXmlContent error:&err];
		
		//Get first element
		TBXMLElement *firstItemElement = [TBXML childElementNamed:@"item" parentElement:xml.rootXMLElement];
		
		//Add into array
		NSArray *modelArr = [self parseXMLElementIntoTimeslot:firstItemElement];
		[self addTimeslot:modelArr];
		
		//Get next
		TBXMLElement *nextElement = [TBXML nextSiblingNamed:@"item" searchFromElement:firstItemElement];
		while (nextElement != nil) {
			
			NSArray *modelArr = [self parseXMLElementIntoTimeslot:nextElement];
			[self addTimeslot:modelArr];
			
			nextElement = [TBXML nextSiblingNamed:@"item" searchFromElement:nextElement];
	}

	}
	@catch (NSException *ex) {
		return nil;
	}
	
}

//- (void)addTimeslot:(TimeslotModel *)model
- (void)addTimeslot:(NSArray *)modelArr
{
	for(TimeslotModel *model in modelArr)
	{
		NSString *group = model.group;
		
		BOOL isGroupExist = [[_groupContentDic allKeys] containsObject:group];
		
		if(!isGroupExist)	//Create the time dictionary and child array
		{
			NSMutableArray *arr = [NSMutableArray arrayWithObject:model];	//Create the array
			
			NSMutableDictionary *timeDict = [NSMutableDictionary dictionaryWithObject:arr forKey:model.day];	//Create the dictionary with child, key is the date
			
			[_groupContentDic setObject:timeDict forKey:group];	//Add the timeDict as value, with key group
		}
		else
		{
			NSMutableDictionary *timeDict = [_groupContentDic objectForKey:group];	//Get the array
			
			if([[timeDict allKeys] containsObject:model.day])	//Check if the date is added already
			{
				NSMutableArray * arr = [timeDict objectForKey:model.day];
				[arr addObject:model];	//Add new item in it
			}
			else	//Not add this date before
			{
				NSMutableArray *arr = [NSMutableArray arrayWithObject:model];	//Create the array
				[timeDict setObject:arr forKey:model.day];	//Add the timeDict as value, with key group
			}
		}
	}
}

- (NSArray *)parseXMLElementIntoTimeslot:(TBXMLElement *)element
{
	TBXMLElement *groupElement = [TBXML childElementNamed:@"group" parentElement:element];
	TBXMLElement *hourElement = [TBXML childElementNamed:@"hour" parentElement:element];
	TBXMLElement *dayElement = [TBXML childElementNamed:@"day" parentElement:element];
	TBXMLElement *typeElement = [TBXML childElementNamed:@"type" parentElement:element];
	
	NSString *strGroup = [TBXML textForElement:groupElement];
	NSString *strHour = [TBXML textForElement:hourElement];
	NSString *strDay = [TBXML textForElement:dayElement];
	NSString *strType = [TBXML textForElement:typeElement];
	
	//Decrypt the hour
	strHour = [self decodeHour:strHour group:strGroup];
	
	//Replace text
	strHour = [strHour stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
	strHour = [strHour stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
	strHour = [strHour stringByReplacingOccurrencesOfString:@"\"" withString:@"'"];

	
	NSLog(@"Before Parse : %@, %@, %@, %@", strGroup, strDay, strType, strHour);
	
	NSMutableArray *retArr = [NSMutableArray array];
	
	//Case 1 : なし
	if([strHour isEqual: @"なし"])
	{
		TimeslotModel *model = [[[TimeslotModel alloc] init] autorelease];
		model.group = strGroup;
		model.hour = @"-";
		model.day = strDay;
		model.type = kTYPE_NIL;
		
		[retArr addObject:model];
	}
	else	
	{
		//Case 2 : 10<br>15<br>20
		//Case 3 : <p class='eme'>9</p><p class='ruby'>16</p>
	
		NSError *err = nil;
		NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@">?(\\d+)<?" options:NSRegularExpressionCaseInsensitive error:&err];
		
		NSArray *matches = [regex matchesInString:strHour options:0 range:NSMakeRange(0, [strHour length])];
		
		for(NSTextCheckingResult *match in matches)
		{
			NSRange matchRange = [match rangeAtIndex:1];
			NSString *val = [strHour substringWithRange:matchRange];
			
			TimeslotModel *model = [[[TimeslotModel alloc] init] autorelease];
			model.group = strGroup;
			model.hour = val;
			model.day = strDay;
			model.type = [EventTypeHelper convertToEventTypeFromString:strType];	//Tempory use the type, it may change
			
			[retArr addObject:model];
		}
		
		//Special Handling for case <p class='eme'>9</p><p class='ruby'>16</p>
		//Because it's different type for different time-slot
		NSRegularExpression *regex2 = [NSRegularExpression regularExpressionWithPattern:@"class='(\\w+)'" options:NSRegularExpressionCaseInsensitive error:&err];
		
		NSArray *matches2 = [regex2 matchesInString:strHour options:0 range:NSMakeRange(0, [strHour length])];
		
		for(int i=0; i<[matches2 count]; i++)	//Iterate to see if any match
		{
			NSTextCheckingResult *match = [matches2 objectAtIndex:i];
			
			NSRange matchRange = [match rangeAtIndex:1];	//Get the type
			NSString *val = [strHour substringWithRange:matchRange];

			//Update type value
			TimeslotModel *model = [retArr objectAtIndex:i];	//Get TimeslotModel from the array
			model.type = [EventTypeHelper convertToEventTypeFromString:val];
		}
	}
	
	
	for(TimeslotModel *model in retArr)
	{
		NSLog(@"After Parse : %@, %@, %@, %@", model.group, model.day, [EventTypeHelper convertToStringFromEventType:model.type], model.hour);
	}
	
	return retArr;
}



- (NSString *)decodeHour:(NSString *)hour group:(NSString *)group
{
	NSArray *arr = [hour componentsSeparatedByString:@"."];
	
	BOOL isNumber = NO;
	NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet];
	for(NSString *str in arr)
	{
		NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:str];
		isNumber = [alphaNumbersSet isSupersetOfSet:stringSet];
		
		if(isNumber == NO)
			break;
	}
	
	//Return directly if not a number
	if(!isNumber)	
		return hour;
	
	double dHour = [hour doubleValue];
	
	double c = ceil(((((dHour * 4) + 2) / 2) - [self decryptGroup:group]) / 5);
	
	NSString *ret = [NSString stringWithFormat:@"%d", (int)c];

	return ret;
}

- (double)decryptGroup:(NSString *)str
{
	if([str isEqualToString:@"A"])
		return 603.4;
	else if ([str isEqualToString:@"B"])
		return 41;
	else if([str isEqualToString:@"C"])
		return 49.2;
	else if([str isEqualToString:@"D"])
		return 123;
	else if([str isEqualToString:@"E"])
		return 304;
	else
		return 0;
}

- (NSString *)requestTimeXml
{
	NSString *ts = [self getCurrentTimestamp];
	
	NSString *strUrl = [NSString stringWithFormat:@"http://pad.zap.jp.net/time.xml?_=%@", ts];
	
	NSLog(@"Request Link: %@", strUrl);
	
	NSURL *aURL = [NSURL URLWithString:strUrl];
	
	NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:aURL];
	[urlRequest addValue:@"http://pad.zap.jp.net/" forHTTPHeaderField:@"Referer"];
	NSURLResponse * response = nil;
	NSError * error = nil;
	NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
	
	NSString *responseContent = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

//	NSLog(@"%@",responseContent);
	
	return responseContent;
}

- (NSString *)getCurrentTimestamp
{
	NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
	
	double t = timeStamp * 1000;
	long long l = (long long)t;
	
	NSString *value =  [[NSNumber numberWithLongLong:l] stringValue];
	
	return value;
}
@end
